using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Security;
using System.Text;
using System.Windows;
using System.Windows.Browser;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using YouVisio.Silverlight.TextDiff.Extensions;

namespace YouVisio.Silverlight.TextDiff
{
    public class TextDiffViewerUI : ITextDiffViewerUI
    {
        private Screen _screen = Screen.Edit;
        private readonly BackgroundWorker _analyserWorker = new BackgroundWorker();
        private readonly BackgroundWorker _reviewChangedWorker = new BackgroundWorker();
        private bool _workerIsRunning = false;

        private Grid _RootGrid { get; set; }
        private Button _TriggerButton { get; set; }
        private TextBox _LeftInput { get; set; }
        private TextBox _RightInput { get; set; }
        private TextBlock _LeftOutputLineNumbers { get; set; }
        private TextDiffOutputBox _LeftOutput { get; set; }
        private TextBlock _RightOutputLineNumbers { get; set; }
        private TextDiffOutputBox _RightOutput { get; set; }
        private ScrollBar _HorizontalScrollBar { get; set; }
        private Grid _OutputOuterGrid { get; set; }
        private Canvas _RectangleCanvas { get; set; }
        private ScrollViewer _OutputScrollViewer { get; set; }
        private Canvas _LinesPreviewCanvas { get; set; }
        private Grid _OutputInnerGrid { get; set; }
        private Button _File1Button { get; set; }
        private TextBlock _File1Label { get; set; }
        private Button _File2Button { get; set; }
        private TextBlock _File2Label { get; set; }
        private TextBlock _MessageLabel { get; set; }
        private Rectangle _WaitCursor { get; set; }

        private readonly Dictionary<string, DependencyObject> _otherElements = new Dictionary<string, DependencyObject>(StringComparer.OrdinalIgnoreCase);
        private List<TextPart> _textPartLines;
        private int _linesCurrentIndex;

        public TextDiffViewerUI(ITextDiffFactory factory, ITemplateSource templateSource, ISettingsSource settingsSource, IInputAccessor inputAccessor, ITextPartFinder textPartFinder, IOutputManager outputManager)
        {
            Factory = factory;
            TemplateSource = templateSource;
            Settings = settingsSource;
            Inputs = inputAccessor;
            PartFinder = textPartFinder;
            Outputs = outputManager;

            _analyserWorker.DoWork += AnalyserWorker_DoWork;
            _analyserWorker.RunWorkerCompleted += AnalyserWorker_RunWorkerCompleted;

            _reviewChangedWorker.DoWork += ReviewChangedWorker_DoWork;
            _reviewChangedWorker.RunWorkerCompleted += ReviewChangedWorker_RunWorkerCompleted;
        }

        public virtual ITextDiffFactory Factory { get; private set; }
        public virtual ITemplateSource TemplateSource { get; private set; }
        protected ISettingsSource Settings { get; private set; }
        protected IInputAccessor Inputs { get; private set; }
        protected ITextPartFinder PartFinder { get; private set; }
        protected IOutputManager Outputs { get; private set; }

        public IDictionary<string, DependencyObject> OtherElements { get { return _otherElements; } }

        public virtual void ParseTemplate(ITemplateSource source)
        {
            this._RootGrid = source.GetTemplateChild<Grid>(TextDiffViewer.Name_RootGrid);
            this._TriggerButton = source.GetTemplateChild<Button>(TextDiffViewer.Name_TriggerButton);
            this._LeftInput = source.GetTemplateChild<TextBox>(TextDiffViewer.Name_LeftInput);
            this._RightInput = source.GetTemplateChild<TextBox>(TextDiffViewer.Name_RightInput);
            this._LeftOutputLineNumbers = source.GetTemplateChild<TextBlock>(TextDiffViewer.Name_LeftOutputLineNumbers);
            this._LeftOutput = source.GetTemplateChild<TextDiffOutputBox>(TextDiffViewer.Name_LeftOutput);
            this._RightOutputLineNumbers = source.GetTemplateChild<TextBlock>(TextDiffViewer.Name_RightOutputLineNumbers);
            this._RightOutput = source.GetTemplateChild<TextDiffOutputBox>(TextDiffViewer.Name_RightOutput);
            this._HorizontalScrollBar = source.GetTemplateChild<ScrollBar>(TextDiffViewer.Name_HorizontalScrollBar);
            this._OutputOuterGrid = source.GetTemplateChild<Grid>(TextDiffViewer.Name_OutputOuterGrid);
            this._RectangleCanvas = source.GetTemplateChild<Canvas>(TextDiffViewer.Name_RectangleCanvas);
            this._OutputScrollViewer = source.GetTemplateChild<ScrollViewer>(TextDiffViewer.Name_OutputScrollViewer);
            this._LinesPreviewCanvas = source.GetTemplateChild<Canvas>(TextDiffViewer.Name_LinesPreviewCanvas);
            this._OutputInnerGrid = source.GetTemplateChild<Grid>(TextDiffViewer.Name_OutputInnerGrid);
            this._File1Button = source.GetTemplateChild<Button>(TextDiffViewer.Name_File1Button);
            this._File1Label = source.GetTemplateChild<TextBlock>(TextDiffViewer.Name_File1Label);
            this._File2Button = source.GetTemplateChild<Button>(TextDiffViewer.Name_File2Button);
            this._File2Label = source.GetTemplateChild<TextBlock>(TextDiffViewer.Name_File2Label);
            this._MessageLabel = source.GetTemplateChild<TextBlock>(TextDiffViewer.Name_MessageLabel);
            this._WaitCursor = source.GetTemplateChild<Rectangle>(TextDiffViewer.Name_WaitCursor);
        }

        public virtual void OnApplyTemplate()
        {
            if (Settings.IsEnableFileDragAndDrop)
            {
                AttachFileDropEvent(this._LeftInput);
                AttachFileDropEvent(this._RightInput);
                AttachFileDropEvent(this._LeftOutput);
                AttachFileDropEvent(this._RightOutput);
            }
            if (Settings.IsVisibleButtonsBar)
            {
                SetUpButton(this._TriggerButton, TriggerButton_Click, Settings.Label_ViewDifferences, true);
                SetUpButton(this._File1Button, FileButton_Click, Settings.Label_File1, Settings.IsEnableFileSelect);
                SetUpButton(this._File2Button, FileButton_Click, Settings.Label_File2, Settings.IsEnableFileSelect);
            }
            else 
            {
                if (this._RootGrid != null && this._RootGrid.RowDefinitions.Count > 0)
                {
                    this._RootGrid.RowDefinitions[0].Height = new GridLength(0);
                }
                if (this._TriggerButton != null)
                {
                    this._TriggerButton.Visibility = Visibility.Collapsed;
                }
                if (this._File1Button != null)
                {
                    this._File1Button.Visibility = Visibility.Collapsed;
                }
                if (this._File2Button != null)
                {
                    this._File2Button.Visibility = Visibility.Collapsed;
                }   
            }
            if (this._LinesPreviewCanvas != null)
            {
                this._LinesPreviewCanvas.Visibility = Settings.IsVisibleLinesPreviewBar.ToVisibility();
                if (!Settings.IsVisibleLinesPreviewBar && this._OutputOuterGrid != null && this._OutputOuterGrid.ColumnDefinitions.Count > 0)
                {
                    this._OutputOuterGrid.ColumnDefinitions[0].Width = new GridLength(0);
                }
            }
            if (this._LeftOutputLineNumbers != null)
            {
                this._LeftOutputLineNumbers.Visibility = Settings.IsVisibleLeftLinesNumbersBar.ToVisibility();
                if(!Settings.IsVisibleLeftLinesNumbersBar && this._OutputInnerGrid != null && this._OutputInnerGrid.ColumnDefinitions.Count > 0)
                {
                    this._OutputInnerGrid.ColumnDefinitions[0].Width = new GridLength(0);
                }
            }
            if (this._RightOutputLineNumbers != null)
            {
                this._RightOutputLineNumbers.Visibility = Settings.IsVisibleRightLinesNumbersBar.ToVisibility();
                if (!Settings.IsVisibleRightLinesNumbersBar && this._OutputInnerGrid != null && this._OutputInnerGrid.ColumnDefinitions.Count > 2)
                {
                    this._OutputInnerGrid.ColumnDefinitions[2].Width = new GridLength(0);
                }
            }
            if(this._HorizontalScrollBar != null)
            {
                this._HorizontalScrollBar.Scroll += HorizontalScrollBar_Scroll;
            }
            if (this._OutputScrollViewer != null)
            {
                this._OutputScrollViewer.LayoutUpdated += OutputScrollViewer_LayoutUpdated;
            }
        }

        private void AttachFileDropEvent(UIElement element)
        {
            if (element != null)
            {
                element.AllowDrop = true;
                element.Drop += FileDrop;
            }
        }

        

        private static void SetUpButton(ButtonBase button, RoutedEventHandler handler, string label, bool isEnabled)
        {
            if (button == null) return;
            if (isEnabled)
            {
                button.Click += handler;
                button.Content = label;
            }
            else button.Visibility = Visibility.Collapsed;
        }

        private void HorizontalScrollBar_Scroll(object sender, ScrollEventArgs e)
        {
            this._LeftOutput.ScrollViewer.ScrollToHorizontalOffset(e.NewValue);
            this._RightOutput.ScrollViewer.ScrollToHorizontalOffset(e.NewValue);
        }

        public virtual Size MeasureOverride(Size availableSize)
        {
            return availableSize;
        }
        public virtual Size ArrangeOverride(Size finalSize)
        {
            UpdateScrollBar();
            return finalSize;
        }

        public virtual void UpdatePreviewLines()
        {
            var allHeight = this._OutputScrollViewer.ActualHeight + this._OutputScrollViewer.ScrollableHeight;
            var winRatio = this._OutputScrollViewer.ActualHeight / allHeight;
            this._LinesPreviewCanvas.Visibility = (winRatio == 1) ? Visibility.Collapsed : Visibility.Visible;
            if (winRatio == 1) return;
            foreach (var child in this._LinesPreviewCanvas.Children)
            {
                var rectangle = child as Rectangle;
                if(rectangle == null) continue;
                if(rectangle.Tag == null) // if this is the window preview
                {
                    rectangle.Height = Math.Max(this._LinesPreviewCanvas.ActualHeight*winRatio, 1);
                    rectangle.SetValue(Canvas.TopProperty, this._LinesPreviewCanvas.ActualHeight * (this._OutputScrollViewer.VerticalOffset / allHeight));
                    continue;
                }
                var info = (BlockInfo)rectangle.Tag;
                rectangle.Height = Math.Max(this._LinesPreviewCanvas.ActualHeight*(info.NumberLines/(double) info.AllLines), 1);
                rectangle.SetValue(Canvas.TopProperty, this._LinesPreviewCanvas.ActualHeight * ((info.FirstLine - 1) / (double)info.AllLines));
            }
        }
        public virtual void SetLeftText(string text)
        {
            if (this._LeftInput == null) return;
            this._LeftInput.Text = text;
            this.SetErrorMessage("");
        }
        public virtual string GetLeftText()
        {
            return this._LeftInput == null ? null : this._LeftInput.Text;
        }

        public virtual void SetRightText(string text)
        {
            if (this._RightInput == null) return;
            this._RightInput.Text = text;
            this.SetErrorMessage("");
        }
        public virtual string GetRightText()
        {
            return this._RightInput == null ? null : this._RightInput.Text;
        }

        public virtual void SetLeftFileName(string fileName)
        {
            if (this._File1Label == null) return;
            this._File1Label.Text = fileName;
            this.SetErrorMessage("");
        }
        public virtual void SetRightFileName(string fileName)
        {
            if (this._File2Label == null) return;
            this._File2Label.Text = fileName;
            this.SetErrorMessage("");
        }
        public virtual void SetErrorMessage(string message)
        {
            if (this._MessageLabel == null) return;
            this._MessageLabel.Text = message;
        }

        public void SetScreen(Screen screen)
        {
            if (Settings.IsEnableTextValidation)
            {
                if (screen == Screen.Preview)
                {
                    if (String.IsNullOrEmpty(this.GetLeftText().Trim()) || String.IsNullOrEmpty(this.GetRightText().Trim()))
                    {
                        this.SetErrorMessage(Settings.Label_Error_PleaseEnterText);
                        return;
                    }
                }
            }
            this._screen = screen;

            if(screen == Screen.Edit)
            {
                // make previous children garbage collectable);
                if (this._LinesPreviewCanvas != null)
                {
                    this._LinesPreviewCanvas.Children.Aggregate(0, (i, ch) =>
                    {
                        var rect = ch as Rectangle;
                        if (rect != null) rect.Tag = null;
                        return i;
                    });
                    this._LinesPreviewCanvas.Children.Clear();
                }

                if (this._RectangleCanvas != null)
                {
                    this._RectangleCanvas.Children.Clear();
                }
                if (this._MessageLabel != null)
                {
                    this._MessageLabel.Text = "";
                }
                if (this._OutputOuterGrid != null) this._OutputOuterGrid.Visibility = Visibility.Collapsed;
                if (this._LeftInput != null) this._LeftInput.Visibility = Visibility.Visible;
                if (this._RightInput != null) this._RightInput.Visibility = Visibility.Visible;

                StopReviewingChangedTextParts();
            }
            if (this._TriggerButton != null)
            {
                this._TriggerButton.Content = this._screen == Screen.Edit ? Settings.Label_ViewDifferences : Settings.Label_EditText;
            }
            if (this._screen == Screen.Preview)
            {
                var tuple = Inputs.GetText(this);

                if (this._WaitCursor != null)
                {
                    this._WaitCursor.Cursor = Cursors.Wait;
                    this._WaitCursor.Visibility = Visibility.Visible;
                }

                this._workerIsRunning = true;
                this._analyserWorker.RunWorkerAsync(tuple);
            }
        }
        private void AnalyserWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var tuple = e.Argument as Tuple<string, string>;

            if (tuple != null) e.Result = PartFinder.Find(tuple.Item1, tuple.Item2);
        }
        private void AnalyserWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            var parts = e.Result as List<TextPart>;

            if(parts == null)
            {
                this._workerIsRunning = false;
                HideWaitCursor();
                this.SetErrorMessage("System Error");
                return;
            }

            if (Settings.IsEnableTextValidation)
            {
                var enumerator = parts.GetEnumerator();

                if (enumerator.MoveNext())
                {
                    var current = enumerator.Current;
                    if (current.Operation == Operation.Equal && !enumerator.MoveNext())
                    {
                        this.SetErrorMessage(Settings.Label_TextIsIdentical);
                        this._workerIsRunning = false;
                        HideWaitCursor();
                        return;
                    }
                }
            }

            if (this._OutputOuterGrid != null) this._OutputOuterGrid.Visibility = Visibility.Visible;
            if (this._LeftInput != null) this._LeftInput.Visibility = Visibility.Collapsed;
            if (this._RightInput != null) this._RightInput.Visibility = Visibility.Collapsed;

            Outputs.GenerateOutput(parts, this);

            this._textPartLines = parts;
            this._linesCurrentIndex = 0;

            ReviewChangedTextParts();

            this._workerIsRunning = false;
            HideWaitCursor();

        }

        private void HideWaitCursor()
        {
            if (this._WaitCursor != null)
            {
                this._WaitCursor.Cursor = Cursors.Arrow;
                this._WaitCursor.Visibility = Visibility.Collapsed;
            }
        }

        private void ReviewChangedWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            var tuple = e.Argument as Tuple<TextPart, TextPart>;

            var dict = new Dictionary<string, int>();
            var counter = new Counter{Value = 0};

            var leftRetriever = Factory.GetNewWordsRetriever();
            leftRetriever.SetTextParts(tuple, dict, counter, true);
            var rightRetriever = Factory.GetNewWordsRetriever();
            rightRetriever.SetTextParts(tuple, dict, counter, false);

            var diffList = Factory.DiffAnalyser.Analyse(EqualityComparer<int>.Default, leftRetriever, rightRetriever);

            var leftWords = leftRetriever.ExtractWords(diffList, Operation.Insert);
            var rightWords = rightRetriever.ExtractWords(diffList, Operation.Delete);

            e.Result = new Tuple<List<Word>, List<Word>, Tuple<TextPart, TextPart>>(leftWords, rightWords, tuple);
        }

        

        private void ReviewChangedWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if(this._LeftOutput.Blocks.Count > 0 && this._RightOutput.Blocks.Count > 0)
            {
                var tuple = e.Result as Tuple<List<Word>, List<Word>, Tuple<TextPart, TextPart>>;
                if(tuple != null) 
                    Outputs.PopulateChangedWordsInlines(
                            this._LeftOutput.Blocks[0] as Paragraph, 
                            this._RightOutput.Blocks[0] as Paragraph, 
                            tuple.Item1, 
                            tuple.Item2, 
                            tuple.Item3);
                ReviewChangedTextParts();
            }
            HideWaitCursor();
        }


        


        private void ReviewChangedTextParts()
        {
            if (this._reviewChangedWorker.IsBusy)
            {
                return;
            }
            if (this._textPartLines == null || this._textPartLines.Count <= this._linesCurrentIndex)
            {
                StopReviewingChangedTextParts();
                return;
            }
            for(var i = this._linesCurrentIndex; i < this._textPartLines.Count; i++)
            {
                var currentPart = this._textPartLines[i];
                if (currentPart.Operation == Operation.Change)
                {
                    TextPart nextPart = null;
                    var next_i = i + 1;
                    if (this._textPartLines.Count > next_i)
                    {
                        nextPart = this._textPartLines[next_i];
                        if (nextPart.Operation != Operation.Delete && nextPart.Operation != Operation.Insert)
                        {
                            nextPart = null;
                        }
                    }
                    if (nextPart != null) next_i++;
                    this._linesCurrentIndex = next_i;
                    this._reviewChangedWorker.RunWorkerAsync(new Tuple<TextPart, TextPart>(currentPart, nextPart));
                    return;
                }
            }
            // no change part fount till the end
            this._linesCurrentIndex = this._textPartLines.Count;
        }
        private void StopReviewingChangedTextParts()
        {
            if(this._reviewChangedWorker.IsBusy)
            {
                this._reviewChangedWorker.CancelAsync();
                this._linesCurrentIndex = this._textPartLines.Count;
            }
        }

        public Tuple<Paragraph, Paragraph> ResetOutputParagraphs()
        {
            this._LeftOutput.Blocks.Clear();
            this._RightOutput.Blocks.Clear();

            var leftBlock = new Paragraph();
            this._LeftOutput.Blocks.Add(leftBlock);
            var rightBlock = new Paragraph();
            this._RightOutput.Blocks.Add(rightBlock);
            return new Tuple<Paragraph, Paragraph>(leftBlock, rightBlock);
        }

        public void OutputParagraphsPopulated()
        {
            this._LeftOutput.UpdateLayout();
            this._RightOutput.UpdateLayout();

            this._LeftOutput.Selection.Select(this._LeftOutput.ContentStart, this._LeftOutput.ContentStart);
            this._RightOutput.Selection.Select(this._RightOutput.ContentStart, this._RightOutput.ContentStart);

            this.UpdateScrollBar();
        }

        public virtual void UpdateScrollBar()
        {
            if (this._HorizontalScrollBar == null) return;
            if(this._LeftOutput.ScrollViewer == null) return;
            var maxScrollable = Math.Max(this._LeftOutput.ScrollViewer.ScrollableWidth,
                                         this._RightOutput.ScrollViewer.ScrollableWidth);
            if(maxScrollable == 0) return;

            this._HorizontalScrollBar.Minimum = 0;
            this._HorizontalScrollBar.ViewportSize = this._LeftOutput.ScrollViewer.ActualWidth;
            this._HorizontalScrollBar.Maximum = maxScrollable;
        }
        public virtual void GenerateLinesPreview(IEnumerable<BlockInfo> blocksList, int allLines)
        {
            if (!Settings.IsVisibleLinesPreviewBar) return;


            foreach (var info in blocksList)
            {
                var rectangle = new Rectangle
                {
                    Width = this._LinesPreviewCanvas.ActualWidth,
                    Height = Math.Max(this._LinesPreviewCanvas.ActualHeight * (info.NumberLines / (double)allLines), 1),
                    Stroke = new SolidColorBrush(Colors.Transparent),
                    Fill = FillByOperation(Settings, info.Operation),
                    Tag = new BlockInfo
                    {
                        AllLines = allLines,
                        FirstLine = info.FirstLine,
                        LastLine = info.LastLine,
                        Operation = info.Operation
                    }
                };
                this._LinesPreviewCanvas.Children.Add(rectangle);
                rectangle.SetValue(Canvas.TopProperty, this._LinesPreviewCanvas.ActualHeight * ((info.FirstLine - 1) / (double)allLines));
                rectangle.SetValue(ToolTipService.ToolTipProperty, LabelByOperation(Settings, info.Operation));
            }

            var allHeight = this._OutputScrollViewer.ActualHeight + this._OutputScrollViewer.ScrollableHeight;
            var winRatio = this._OutputScrollViewer.ActualHeight / allHeight;

            var windowPreview = new Rectangle
            {
                Width = this._LinesPreviewCanvas.ActualWidth - (Settings.PreviewWindowSideMargin * 2),
                Height = Math.Max(this._LinesPreviewCanvas.ActualHeight * winRatio, 1),
                Fill = Settings.PreviewWindowFillBrush,
                Stroke = Settings.PreviewWindowStrokeBrush,
                Margin = new Thickness(Settings.PreviewWindowSideMargin, 0, Settings.PreviewWindowSideMargin, 0)
            };
            this._LinesPreviewCanvas.Children.Add(windowPreview);
            windowPreview.SetValue(Canvas.TopProperty, this._LinesPreviewCanvas.ActualHeight * (this._OutputScrollViewer.HorizontalOffset / allHeight));
            windowPreview.SetValue(ToolTipService.ToolTipProperty, Settings.Label_VisibleWindow);
        }

        public void GenerateLineNumbers(bool hasLineNumbers, string numbers, int linesCount)
        {
            if (hasLineNumbers && linesCount > 0)
            {
                var linesString = numbers;
                if (Settings.IsVisibleLeftLinesNumbersBar && this._LeftOutputLineNumbers != null)
                    this._LeftOutputLineNumbers.Text = linesString;
                if (Settings.IsVisibleRightLinesNumbersBar && this._RightOutputLineNumbers != null)
                    this._RightOutputLineNumbers.Text = linesString;
            }
        }

        public void GenerateColoredBackgrounds(List<BlockInfo> blockInfos, int linesCount)
        {
            if (blockInfos.Count == 0 || this._RectangleCanvas == null) return;



            var lineHeight = Math.Max(this._LeftOutput.LineHeight, this._RightOutput.LineHeight);// we need that in case one box is empty

            var binding = new Binding
            {
                Source = this._OutputScrollViewer,
                Mode = BindingMode.OneWay,
                Path = new PropertyPath("ViewportWidth")
            };

            foreach (var blockInfo in blockInfos)
            {
                var height = lineHeight * blockInfo.NumberLines;
                var top = (blockInfo.FirstLine - 1) * lineHeight;

                var rectangle = new Rectangle
                {
                    Height = height,
                    Width = 100,
                    Fill = FillByOperation(Settings, blockInfo.Operation)
                };
                rectangle.SetBinding(FrameworkElement.WidthProperty, binding);
                this._RectangleCanvas.Children.Add(rectangle);
                rectangle.SetValue(Canvas.LeftProperty, 0.0);
                rectangle.SetValue(Canvas.TopProperty, top);
            }
        }

        private static Brush FillByOperation(ISettingsSource settings, Operation operation)
        {
            switch (operation)
            {
                case Operation.Insert:
                    return settings.BlockInsertedBrush;
                case Operation.Delete:
                    return settings.BlockDeletedBrush;
                case Operation.Change:
                    return settings.BlockChangedBrush;
            }
            throw new ArgumentException("Unexpected operation: " + operation);
        }
        private static string LabelByOperation(ISettingsSource settings, Operation operation)
        {
            switch (operation)
            {
                case Operation.Insert:
                    return settings.Label_Inserted;
                case Operation.Delete:
                    return settings.Label_Deleted;
                case Operation.Change:
                    return settings.Label_Changed;
            }
            throw new ArgumentException("Unexpected operation: " + operation);
        }

        private void OutputScrollViewer_LayoutUpdated(object sender, EventArgs e)
        {
            this.UpdatePreviewLines();
        }


        private void TriggerButton_Click(object sender, RoutedEventArgs e)
        {
            if (this._workerIsRunning) return;
            SetScreen(this._screen == Screen.Edit ? Screen.Preview : Screen.Edit);
            if (this._screen == Screen.Edit)
            {
                if (this._File1Label != null)
                {
                    this._File1Label.Text = "";
                }
                if (this._File2Label != null)
                {
                    this._File2Label.Text = "";
                }
            }
        }

        private void FileButton_Click(object sender, RoutedEventArgs e)
        {
            if (this._workerIsRunning) return;
            if (this._screen == Screen.Preview)
            {
                this.SetScreen(Screen.Edit);
            }

            var isLeft = ((FrameworkElement)(sender)).Name == TextDiffViewer.Name_File1Button;
            try
            {
                this.Inputs.SelectFile(this, isLeft);
            }catch(SecurityException) {}
            
        }

        private void FileDrop(object sender, DragEventArgs e)
        {
            if (this._workerIsRunning) return;
            IDataObject data = e.Data;
            if (data.GetDataPresent(DataFormats.FileDrop))
            {
                var files = data.GetData(DataFormats.FileDrop) as FileInfo[];
                if (files != null && files.Length > 0)
                {
                    var isLeft = ((FrameworkElement)(sender)).Name.StartsWith("Left");
                    if(Inputs.SetFiles(this, files, isLeft))
                    {
                        this.SetScreen(Screen.Edit);
                    }
                }
            }
        }

    }
}